﻿using System.Linq.Expressions;
using Dyao.Book.Entity;
using Dyao.Book.Repository.Abstractions;
using Foundation.Core;

namespace Dyao.Book.Repository.Repositories
{
    using Foundation.Replacement;

    public class BookCatalogueRepository : DataRepository<BookCatalogueEntity>, IBookCatalogueRepository
    {
        /// <inheritdoc cref="IBookCatalogueRepository.BulkInsertAsync"/>
        public new Task BulkInsertAsync(IEnumerable<BookCatalogueEntity> entities, CancellationToken cancellationToken)
        {
            return base.BulkInsertAsync(entities, cancellationToken);
        }

        /// <inheritdoc cref="IBookCatalogueRepository.BulkUpdateAsync"/>
        public new Task BulkUpdateAsync(IEnumerable<BookCatalogueEntity> entities, Expression<Func<BookCatalogueEntity, object>> updateSelector, CancellationToken cancellationToken = default)
        {
            return base.BulkUpdateAsync(entities, op =>
            {
                op.ColumnPrimaryKeyExpression = key => new { key.ID };
                op.IncludeOnUpdateExpression = updateSelector;
            }, cancellationToken);
        }

        /// <inheritdoc cref="IBookCatalogueRepository.BulkDeleteAsync"/>
        public new Task BulkDeleteAsync(IEnumerable<BookCatalogueEntity> entities, CancellationToken cancellationToken = default)
        {
            return base.BulkDeleteAsync(entities, op =>
            {
                op.ColumnPrimaryKeyExpression = key => new { key.ID };
            }, cancellationToken);
        }

        /// <inheritdoc cref="IBookCatalogueRepository.GetListByBookIdAsync"/>
        public async Task<List<T>> GetListByBookIdAsync<T>(string bookId, Expression<Func<BookCatalogueEntity, T>> selector, CancellationToken cancellationToken)
        {
            var query = this.GetQueryable()
                .Where(bc => bc.BookId == bookId)
                .OrderBy(bc => bc.VolumeId)
                .ThenBy(bc => bc.CatalogueSeq)
                .Select(selector);

            return await query.ToListAsync(cancellationToken);
        }

        /// <inheritdoc cref="IBookCatalogueRepository.GetListByIdsAsync"/>
        public async Task<List<T>> GetListByIdsAsync<T>(List<string> ids, Expression<Func<BookCatalogueEntity, T>> selector, CancellationToken cancellationToken)
        {
            if (ids.IsNullOrEmpty())
                return Enumerable.Empty<T>().ToList();

            var query = this.GetQueryable()
                .Where(bc => ids.Contains(bc.ID))
                .AsNoTracking()
                .Select(selector);

            return await query.ToListAsync(cancellationToken);
        }

        /// <inheritdoc cref="IBookCatalogueRepository.GetListByIdsAsync"/>
        public async Task<BookCatalogueEntity> GetByIdAsync(string id, CancellationToken cancellationToken)
        {
            var query = this.GetQueryable()
                .Where(bc => id == bc.ID);

            return await query.FirstOrDefaultAsync(cancellationToken);
        }

        /// <inheritdoc cref="IBookCatalogueRepository.GetNotMatchListByBookIdAsync"/>
        public async Task<List<T>> GetNotMatchListByBookIdAsync<T>(string bookId, Expression<Func<BookCatalogueEntity, T>> selector, CancellationToken cancellationToken)
        {
            var query = this.GetQueryable()
                .Where(bc => bc.BookId == bookId)
                .Where(bc => !bc.IsFree)
                .Where(bc => !bc.IsMatchSource)
                .OrderBy(bc => bc.VolumeId)
                .ThenBy(bc => bc.CatalogueSeq)
                .Select(selector);

            return await query.ToListAsync(cancellationToken);
        }

        /// <inheritdoc cref="IBookCatalogueRepository.GetNotCrawlCompalteByBookIdAsync"/>
        public async Task<List<T>> GetNotCrawlCompalteByBookIdAsync<T>(string bookId, Expression<Func<BookCatalogueEntity, T>> selector, CancellationToken cancellationToken)
        {
            var query = this.GetQueryable()
                .Where(bc => bc.BookId == bookId)
                .Where(bc => !bc.CrawlComplete)
                .Where(bc => bc.IsMatchSource)
                .OrderBy(bc => bc.VolumeId)
                .ThenBy(bc => bc.CatalogueSeq)
                .Select(selector);

            return await query.ToListAsync(cancellationToken);
        }
    }
}
